package org.wang.generalcode.modules.exam.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.jfinal.kit.Kv;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.util.FileCopyUtils;
import org.wang.generalcode.modules.exam.common.template.BaseTemplate;
import org.wang.generalcode.modules.exam.common.template.EnjoyTemplate;
import org.wang.generalcode.modules.exam.constants.EnumConstants;
import org.wang.generalcode.modules.exam.constants.SystemConstants;
import org.wang.generalcode.modules.exam.converter.TestPaperInfoConverter;
import org.wang.generalcode.modules.exam.mapper.QuestionInfoMapper;
import org.wang.generalcode.modules.exam.mapper.TestPaperInfoMapper;
import org.wang.generalcode.modules.exam.mapper.TestPaperQuestionInfoMapper;
import org.wang.generalcode.modules.exam.pojo.entity.QuestionInfoEntity;
import org.wang.generalcode.modules.exam.pojo.entity.TestPaperInfoEntity;
import org.wang.generalcode.modules.exam.pojo.entity.TestPaperQuestionInfoEntity;
import org.wang.generalcode.modules.exam.pojo.param.TestPaperInfoParams;
import org.wang.generalcode.modules.exam.pojo.vo.TestPaperInfoVO;
import org.wang.generalcode.modules.exam.service.TestPaperInfoService;
import org.wang.generalcode.modules.exam.utils.*;
import org.wang.generalcode.support.base.BaseServiceImpl;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 试卷信息表服务实现类
 *
 * @author wz
 * @since 2024-11-29
 */
@Service
@RequiredArgsConstructor
public class TestPaperInfoServiceImpl extends BaseServiceImpl<TestPaperInfoMapper, TestPaperInfoEntity> implements TestPaperInfoService {

    private final TestPaperInfoConverter testpaperinfoConverter;

    @Resource
    private QuestionInfoMapper questionInfoMapper;

    @Resource
    private TestPaperQuestionInfoMapper testPaperQuestionInfoMapper;

    /**
     * 获取试卷信息表分页列表
     *
     * @param queryParams 查询参数
     * @return {@link IPage<TestPaperInfoVO>} 试卷信息表分页列表
     */
    @Override
    public IPage<TestPaperInfoVO> getTestPaperInfoPage(IPage<TestPaperInfoVO> page, TestPaperInfoParams queryParams) {
        return page.setRecords(baseMapper.getTestPaperInfoPage(page, queryParams));
    }

    @Override
    public void printPaperInfo(String testPaperInfoId, HttpServletResponse response) {
        TestPaperInfoEntity testPaperInfo = baseMapper.selectById(testPaperInfoId);
        List<TestPaperQuestionInfoEntity> testPaperInfoList = testPaperQuestionInfoMapper.selectList(Wrappers.<TestPaperQuestionInfoEntity>lambdaQuery().eq(TestPaperQuestionInfoEntity::getTestPaperInfoId, testPaperInfoId));
        List<Integer> questionIds = testPaperInfoList.stream().map(TestPaperQuestionInfoEntity::getQuestionInfoId).collect(Collectors.toList());
        List<QuestionInfoEntity> testPaperQuestionDtoList = questionInfoMapper.selectList(Wrappers.<QuestionInfoEntity>lambdaQuery().in(QuestionInfoEntity::getId, questionIds));
        /**将 options 数组 转换成 数组 optionsList*/
        testPaperQuestionDtoList.forEach(questionInfoEntity -> {
            String options = questionInfoEntity.getOptions();
            if (!StrUtil.isEmptyIfStr(options)) {
                ObjectMapper objectMapper = new ObjectMapper();
                try {
                    List<Map<String, Object>> optionsList = objectMapper.readValue(options, new TypeReference<>() {
                    });
                    questionInfoEntity.setOptionsList(optionsList);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });

        Kv data = Kv.create().set("testPaperQuestionList", this.groupQuestion(testPaperQuestionDtoList))
                .set("title", testPaperInfo.getName());
        String htmlName = SpellUtils.getSpell(testPaperInfo.getName()) + SystemConstants.HTML;
        String outDirPath = "/paperPrint" + SystemConstants.FILE_SEPARATOR
                + testPaperInfoId + SystemConstants.FILE_SEPARATOR;
        String paperTemplateSavePath = FileUtils.getUploadPath() + outDirPath;
        BaseTemplate template = new EnjoyTemplate(SystemConstants.PAPER_INFO_TEMPLATE, paperTemplateSavePath);
//        template.generateTemplateToOss(data, outDirPath, htmlName, fileUpload);
        template.generateTemplate(data, htmlName);
        String downloadUrl = outDirPath + htmlName;
        testPaperInfo.setHtmlDownloadUrl(downloadUrl);
        super.update(Wrappers.lambdaUpdate(TestPaperInfoEntity.class).set(TestPaperInfoEntity::getHtmlDownloadUrl, downloadUrl)
                .eq(TestPaperInfoEntity::getId, testPaperInfoId));

        String path = SystemConstants.DEFAULT_LOCAL_TMP_FILE_UPLOAD_PATH + downloadUrl;
        String pdfPath = SystemConstants.DEFAULT_LOCAL_TMP_FILE_UPLOAD_PATH + downloadUrl.replace(".html", ".pdf");
        try {
            HtmlToPdfUtils.generatePdf(new FileInputStream(path), pdfPath);
            FileCopyUtils.copy(new FileInputStream(pdfPath), response.getOutputStream());
        } catch (Exception e) {
            log.error("View document exception, document path is [{}]" + pdfPath);
        }
    }

    /**
     * 对试卷试题进行分组
     * @param testPaperQuestionDtoList
     * @return
     */
    public List<Map> groupQuestion(List<QuestionInfoEntity> testPaperQuestionDtoList) {
        List<Map> testPaperQuestionGroupList = new ArrayList<>();
        int number = 1;
        for (EnumConstants.QuestionType questionType : EnumConstants.QuestionType.values()) {
            Map item = new HashMap<>();
            int questionTypeValue = questionType.getValue();
            List<QuestionInfoEntity> groupQuestionList = testPaperQuestionDtoList.stream()
                    .filter(question -> question.getQuestionType().intValue() == questionTypeValue)
                    .collect(Collectors.toList());
            if (ObjectUtils.isNotEmpty(groupQuestionList)) {
                item.put("groupQuestionTypeTitle", questionType.getName());
                // 答题类型序号
                item.put("groupQuestionTypeTitleNumber", NumberUtils.numberToChinese(number));
                item.put("groupQuestionList", groupQuestionList);
                testPaperQuestionGroupList.add(item);
                number++;
            }
        }
        return testPaperQuestionGroupList;
    }
}
